﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Hammock;
using Hammock.Authentication.OAuth;
using Hammock.Serialization;
using Hammock.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using WeiboPlus.Service;
using WeiboPlus.Models;

namespace WeiboPlus.Sina
{
    public class SinaStatusService : StatusServiceBase
    {
        protected override IList<SNSStatus> Mapping(string res, SNSResult result)
        {
            List<SNSStatus> statuses = null;
            try
            {
                if (res.Contains("error"))
                {
                    //TODO HANDLE ERROR:
                    // Refresh / Notify user to refresh
                    return statuses;
                }
                string content = "";
                if (!res.StartsWith("["))
                {
                    content = string.Format("[{0}]", res);
                }
                else
                    content = res;
                JObject o = JObject.Parse("{\"statuses\":" + content + "}");

                statuses = o.SelectToken("statuses").Select(
                    s => Factory.GetMapping<JToken, SNSStatus>().Map(s)
                    ).ToList();
            }
            catch (Exception)
            {
                throw;
            }

            return statuses;
        }


        protected override SNSStatus MappingSingle(string res, SNSResult result)
        {
            SNSStatus status = null;
            try
            {
                var content = res;
                if (content.Contains("error"))
                {
                    //TODO HANDLE ERROR:
                    // Refresh / Notify user to refresh
                    return status;
                }
                JObject o = JObject.Parse(content);

                status = Factory.GetMapping<JToken, SNSStatus>().Map(o);
            }
            catch (Exception)
            {
                throw;
            }
            return status;
            //return base.MappingSingle(res);
        }

        protected override string[] GetParamtersList(SNSType type)
        {
            string[] list;
            switch (type)
            {
                case SNSType.HomeStatus:
                    list = new string[] { 
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE,
                        SNSParametersConstants.BASE_APP,
                        SNSParametersConstants.FEATURE
                    };
                    break;
                case SNSType.UserStatus:
                    list = new string[] { 
                        SNSParametersConstants.UID,
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE,
                        SNSParametersConstants.BASE_APP,
                        SNSParametersConstants.FEATURE
                    };
                    break;
                case SNSType.MentionsStatus:
                    list = new string[] { 
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE
                    };
                    break;
                case SNSType.SearchStatus:
                    list = new string[] { 
                        SNSParametersConstants.Q,
                        SNSParametersConstants.COUNT,
                        SNSParametersConstants.PAGE
                    };
                    break;
                case SNSType.PublicStatus:
                    list = new string[] { 
                        SNSParametersConstants.COUNT,
                        SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.AddStatus:
                    list = new string[] { 
                        SNSParametersConstants.STATUS_TEXT
                    };
                    break;
                case SNSType.RepostStatus:
                    list = new string[] 
                    { 
                        SNSParametersConstants.ID,
                        SNSParametersConstants.STATUS_TEXT,
                        SNSParametersConstants.IS_COMMENT };
                    break;
                case SNSType.CommentsToMe:
                    list = new string[] { 
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE,
                    };
                    break;
                case SNSType.CommentsByMe:
                    list = new string[] { 
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE
                    };
                    break;
                case SNSType.CommentsByID:
                    list = new string[] { 
                        SNSParametersConstants.ID,
                        SNSParametersConstants.SINCE_ID,
                        SNSParametersConstants.MAX_ID ,
                        SNSParametersConstants.COUNT,
                        //SNSParametersConstants.PAGE
                    };
                    break;
                case SNSType.AddComment:
                    list = new string[]
                    { 
                        SNSParametersConstants.ID,
                        SNSParametersConstants.COMMENT,
                        SNSParametersConstants.CID,
                        SNSParametersConstants.WITHOUT_MENTION,
                        SNSParametersConstants.COMMENT_ORI
                    };
                    break;
                case SNSType.DeleteComment:
                    list = new string[] { 
                        //SNSParametersConstants.COUNT,
                        //SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.Upload:
                    list = new string[] { 
                        SNSParametersConstants.STATUS_TEXT,
                        SNSParametersConstants.PIC,
                        SNSParametersConstants.LAT,
                        SNSParametersConstants.LONG
                        //SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.QueryCount:
                    list = new string[] {
                       SNSParametersConstants.UID
                       //SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.ResetCount:
                    list = new string[] { 
                        SNSParametersConstants.TYPE
                        //SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.QueryCounts:
                    list = new string[] { 
                        SNSParametersConstants.IDS
                        //SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.TrendsByHour:
                    list = new string[] { 
                        //SNSParametersConstants.
                        SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.TrendsByDay:
                    list = new string[] { 
                        //SNSParametersConstants.
                        SNSParametersConstants.BASE_APP
                    };
                    break;
                case SNSType.TrendsByWeek:
                    list = new string[] { 
                        //SNSParametersConstants.
                        SNSParametersConstants.BASE_APP
                    };
                    break;
                default:
                    list = new string[] 
                    { 
                    };
                    break;
            }
            return list;
        }

        protected override int ValidateResponse(RestResponse res, out string msg)
        {
            if (res.Content.StartsWith("<"))
            {
                msg = res.Content;
                return 0;
            }

            if (string.IsNullOrEmpty(res.Content))
            {
                msg = "no data";
                return 99;
            }

            if (res.Content.Contains("error") && res.Content.Contains("error_code"))
            {
                msg = res.Content;
                //TO-DO HANDLE ERROR
                return 0;
            }
            msg = "ok";

            return 1;
        }

        protected override void Initialize()
        {
            //throw new NotImplementedException();
            STATUS_HOME_TIMELINE = "/2/statuses/home_timeline.json";
            STATUS_MENTIONS_TIMELINE = "/2/statuses/mentions.json";
            STATUS_SEARCH_TIMELINE = "/2/search/topics.json";
            STATUS_USER_TIMELINE = "/2/statuses/user_timeline.json";
            STATUS_UPDATE = "/2/statuses/update.json";
            STATUS_REPOST = "/2/statuses/repost.json";
            STATUS_REPLY = "/2/statuses/comment.json";
            COMMENT_BY_ME = "/2/comments/by_me.json";
            COMMENT_TO_ME = "/2/comments/to_me.json";
            COMMENT_BY_ID = "/2/comments/show.json";
            COMMENT_ADD = "/2/comments/create.json";
            COMMENT_DELETE = "/2/comments/destroy.json";
            STATUS_UPLOAD = "/2/statuses/upload.json";
            QUERY_COUNT = "/2/remind/unread_count.json";
            RESET_COUNT = "/2/remind/set_count.json";
            COUNTS = "/2/statuses/counts.json";
            TRENDS_HOURLY = "/2/trends/hourly.json";
            TRENDS_DAILY = "/2/trends/daily.json";
            TRENDS_WEEKLY = "/2/trends/weekly.json";
        }

        public override void GetTimeline(SNSRequest snsRequest, Action<IList<SNSStatus>, SNSResult> action)
        {
            if (snsRequest.Type == SNSType.SearchStatus && snsRequest.Parameters.FirstOrDefault(p => p.Name == SNSParametersConstants.MAX_ID) != null)
            {
                if (action != null)
                    action(null, new SNSResult() { IsSuccess = false, Message = "新浪不支持搜索分页显示" });
                return;
            }
            base.GetTimeline(snsRequest, action);
        }

        protected override T MappingSingle<T>(string res, SNSResult result)
        {
            JObject o = JObject.Parse(res);

            return Factory.GetMapping<JToken, T>().Map(o);
        }

        protected override IList<T1> Mapping<T1>(string res, SNSResult result)
        {
            List<T1> lists = null;
            try
            {
                if (res.Contains("error") && !res.StartsWith("{\"statuses\":"))
                {
                    //TODO HANDLE ERROR:
                    // Refresh / Notify user to refresh
                    return lists;
                }

                string content = "";
                if (res.StartsWith("["))
                {
                    content = "{\"statuses\":" + res + "}";
                }

                JObject o = JObject.Parse(res);
                if (o.SelectToken("statuses") != null)
                    lists = o.SelectToken("statuses").Select(
                        s => Factory.GetMapping<JToken, T1>().Map(s)
                        ).ToList();
                else if (o.SelectToken("comments") != null)
                    lists = o.SelectToken("comments").Select(
                       s => Factory.GetMapping<JToken, T1>().Map(s)
                       ).ToList();
            }
            catch (Exception)
            {
                throw;
            }

            return lists;
        }

        public override void ResetCounts(SNSRequest request, Action<SNSCounts, SNSResult> action)
        {
            var type = request.Parameters.FirstOrDefault<SNSParameter>(p => p.Name == SNSParametersConstants.TYPE_SINA);
            if (type != null)
            {
                var req = new SNSRequest() {  Type = SNSType.ResetCount};
                req.Parameters.Add(new SNSParameter(SNSParametersConstants.TYPE, type.Value));
                base.ResetCounts(req, action);
            }

            //if (action != null)
            //    action(null, new SNSResult() { IsSuccess = true });
        }

        public override void QueryCounts(SNSRequest request, Action<SNSCounts, SNSResult> action)
        {
            //var req = new SNSRequest();
            //req.Parameters.Add(new SNSParameter(SNSParametersConstants.UID, Account.UserLite.Id + ""));
            base.QueryCounts(request, action);
        }
    }
}
